#include "nty_coroutine.h"

#include <arpa/inet.h>
//#include "kvstore.h"
#include "kvs.h"

#define MAX_CLIENT_NUM 1000000
#define TIME_SUB_MS(tv1, tv2) ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000)
#define PORT_NUM 1

void server_reader(void *arg)
{
    int fd = *(int *)arg;
    kvs_free(arg);
    int ret = 0;

    content_t content;

    struct pollfd fds;
    fds.fd = fd;
    fds.events = POLLIN;

    while (1)
    {

        char *rbuf = content.rbuffer;
        char *wbuf = content.wbuffer;
        ret = nty_recv(fd, rbuf, BUFFER_LENGTH, 0);
        if (ret > 0)
        {
            if (fd > MAX_CLIENT_NUM)
            {
                printf("read from server: %.*s\n", ret, rbuf);
            }

            //kvs_request(&content);

            ret = nty_send(fd, wbuf, strlen(wbuf), 0);
            if (ret == -1)
            {
                nty_close(fd);
                break;
            }

            
            memset(content.wbuffer, 0, BUFFER_LENGTH);
            content.wlen = 0;
        }
        else if (ret == 0)
        {
            nty_close(fd);
            break;
        }
    }
}

void server(void *arg)
{

    unsigned short port = *(unsigned short *)arg;
    kvs_free(arg);

    int fd = nty_socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0)
        return;

    struct sockaddr_in local, remote;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;
    bind(fd, (struct sockaddr *)&local, sizeof(struct sockaddr_in));

    listen(fd, 20);

    struct timeval tv_begin;
    gettimeofday(&tv_begin, NULL);

    while (1)
    {
        socklen_t len = sizeof(struct sockaddr_in);
        int cli_fd = nty_accept(fd, (struct sockaddr *)&remote, &len);

        if (cli_fd % 1000 == 999)
        {

            struct timeval tv_cur;
            memcpy(&tv_cur, &tv_begin, sizeof(struct timeval));

            gettimeofday(&tv_begin, NULL);
            int time_used = TIME_SUB_MS(tv_begin, tv_cur);

            printf("client fd : %d, time_used: %d\n", cli_fd, time_used);
        }
        // printf("new client comming\n");

        nty_coroutine *read_co;
        int *arg = kvs_malloc(sizeof(int));
        *arg = cli_fd;
        nty_coroutine_create(&read_co, server_reader, arg);
    }
}

int nty_entry(int port)
{
    nty_coroutine *co = NULL;

    int i = 0;
    unsigned short base_port = port;
    for (i = 0; i < PORT_NUM; i++)
    {
        unsigned short *ports = calloc(1, sizeof(unsigned short));
        *ports = base_port + i;
        LOG("listen at %d\n", *ports);
        nty_coroutine_create(&co, server, ports); ////////no run
    }

    nty_schedule_run(); // run

    return 0;
}
